#include "base/Properties.h"
#include <gtest/gtest.h>

// 1. 基本 set / get 整数
TEST(PropertyBagTest, SetGetInt) {
  PropertyBag bag;
  bag.set("age", 18);
  EXPECT_EQ(bag["age"].toInt(0), 18);
  EXPECT_EQ(bag["none"].toInt(-1), -1);  // 缺失返回默认值
}

// 2. 浮点
TEST(PropertyBagTest, SetGetDouble) {
  PropertyBag bag;
  bag["pi"] = 3.14159;
  EXPECT_DOUBLE_EQ(bag["pi"].toDouble(0.0), 3.14159);
  EXPECT_DOUBLE_EQ(bag["bad"].toDouble(2.71), 2.71);
}

// 3. 布尔
TEST(PropertyBagTest, SetGetBool) {
  PropertyBag bag;
  bag.set("enable", true);
  EXPECT_TRUE(bag["enable"].toBool(false));
  EXPECT_FALSE(bag["missing"].toBool(false));
}

// 4. 字符串
TEST(PropertyBagTest, SetGetString) {
  PropertyBag bag;
  bag["name"] = std::string("Moonshot");
  EXPECT_EQ(bag["name"].toString(""), "Moonshot");
  EXPECT_EQ(bag["empty"].toString("default"), "default");
}

// 6. 链式 set
TEST(PropertyBagTest, ChainSet) {
  PropertyBag bag;
  bag.set("a", 1).set("b", 2.0).set("c", true);
  EXPECT_EQ(bag["a"].toInt(), 1);
  EXPECT_DOUBLE_EQ(bag["b"].toDouble(), 2.0);
  EXPECT_TRUE(bag["c"].toBool());
}

// 7. 中括号赋值
TEST(PropertyBagTest, BracketAssign) {
  PropertyBag bag;
  bag["x"] = 42;
  bag["y"] = 3.14;
  bag["z"] = std::string("hello");
  EXPECT_EQ(bag["x"].toInt(), 42);
  EXPECT_DOUBLE_EQ(bag["y"].toDouble(), 3.14);
  EXPECT_EQ(bag["z"].toString(), "hello");
}

// 8. 删除
TEST(PropertyBagTest, Remove) {
  PropertyBag bag;
  bag["tmp"] = 100;
  EXPECT_TRUE(bag.contains("tmp"));
  EXPECT_TRUE(bag.remove("tmp"));
  EXPECT_FALSE(bag.contains("tmp"));
  EXPECT_FALSE(bag.remove("tmp"));  // 再次删除返回 false
}

// 9. 清空
TEST(PropertyBagTest, Clear) {
  PropertyBag bag;
  bag["a"] = 1;
  bag["b"] = 2;
  EXPECT_EQ(bag.size(), 2);
  bag.clear();
  EXPECT_EQ(bag.size(), 0);
  EXPECT_FALSE(bag.contains("a"));
}

// 10. 常对象只读
TEST(PropertyBagTest, ConstRead) {
  PropertyBag bag;
  bag["val"] = 123;
  const PropertyBag& cbag = bag;
  EXPECT_EQ(cbag["val"].toInt(0), 123);
  EXPECT_EQ(cbag["none"].toInt(999), 999);
}

// 11. 类型不匹配返回默认值
TEST(PropertyBagTest, TypeMismatch) {
  PropertyBag bag;
  bag["str"] = std::string("not a number");
  EXPECT_EQ(bag["str"].toInt(88), 88);      // 类型不符
  EXPECT_DOUBLE_EQ(bag["str"].toDouble(1.5), 1.5);
}

// 12. PropertyBag 嵌套
TEST(PropertyBagTest, NestedPropertyBag) {
  PropertyBag bag;
  PropertyBag inner_bag;
  inner_bag.set("nested_int", 42);

  bag.set("inner", inner_bag);

  auto retrieved = bag["inner"].toObject();
  EXPECT_EQ(retrieved["nested_int"].toInt(0), 42);
}

// toVec 测试
TEST(PropertyBagTest, VecTypes) {
  PropertyBag bag;
  bag.set("int_vec", std::vector<int>{1, 2, 3});
  bag.set("str_vec", std::vector<std::string>{"a", "b", "c"});
  
  auto int_vec = bag["int_vec"].toVec<int>({});
  EXPECT_EQ(int_vec.size(), 3);
  EXPECT_EQ(int_vec[2], 3);

  auto str_vec = bag["str_vec"].toVec<std::string>({});
  EXPECT_EQ(str_vec.size(), 3);
  EXPECT_EQ(str_vec[1], "b");
}

// to 测试
TEST(PropertyBagTest, TypeConversion) {
  PropertyBag bag;
  bag.set("int_val", 123);
  bag.set("double_val", 3.14);
  bag.set("bool_val", true);
  bag.set("str_val", std::string("hello"));
  bag.set("int64_val", 1234567890123456789);
  bag.set("int32_val", 1234567890);
  
  EXPECT_EQ(bag["int_val"].to<int>(), 123);
  EXPECT_EQ(bag["double_val"].to<double>(), 3.14);
  EXPECT_EQ(bag["bool_val"].to<bool>(), true);
  EXPECT_EQ(bag["str_val"].to<std::string>(), "hello");
  EXPECT_EQ(bag["int64_val"].to<int64_t>(), 1234567890123456789);
  EXPECT_EQ(bag["int32_val"].to<int32_t>(), 1234567890);
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}